package com.pkk.cloud.support.admin.service.impl;

import static com.pkk.cloud.support.admin.constand.OauthAdminConstand.DEFAULT_RESOURCE_TYPE_CLIENT;
import static com.pkk.cloud.support.admin.constand.OauthAdminConstand.DEFAULT_RESOURCE_TYPE_SERVER;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.pkk.cloud.support.admin.bo.OauthServerClientBo;
import com.pkk.cloud.support.admin.dto.req.client.OauthClientDelReqDto;
import com.pkk.cloud.support.admin.dto.req.client.OauthClientIdReqDto;
import com.pkk.cloud.support.admin.dto.req.client.OauthClientPageReqDto;
import com.pkk.cloud.support.admin.dto.req.client.OauthVisitClientBindClientScopeReqDto;
import com.pkk.cloud.support.admin.dto.resp.client.OauthClientDetailRespDto;
import com.pkk.cloud.support.admin.dto.resp.server.OauthServerClientByClientVistiRespDto;
import com.pkk.cloud.support.admin.dto.resp.server.OauthServerClientScopeByClientRespDto;
import com.pkk.cloud.support.admin.mybatis.client.PenguinSysClientScopeBusinessMapper;
import com.pkk.cloud.support.admin.service.PenguinSysClientScopeBusinessService;
import com.pkk.cloud.support.admin.service.PenguinSysServerService;
import com.pkk.cloud.support.oauth2.client.detail.client.entity.PenguinOauthClient;
import com.pkk.cloud.support.oauth2.client.detail.client.entity.PenguinOauthClientScope;
import com.pkk.components.rpc.page.Page;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @description: 客户端和scope的业务类
 * @author: peikunkun
 * @create: 2020-03-30 15:48
 **/
@Slf4j
@Service
public class PenguinSysClientScopeBusinessServiceImpl implements PenguinSysClientScopeBusinessService {


  @Resource
  private PenguinSysServerService penguinSysServerService;
  @Resource
  private PenguinSysClientScopeBusinessMapper penguinSysClientScopeBusinessMapper;


  /**
   * @Description: 验证是否存在客户端
   * @Param: clientType
   * @Param clientId
   * @Param ownServerId
   * @return: boolean
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 上午 11:33
   */
  @Override
  public boolean countClientExists(Integer clientType, String clientId, Long ownServerId, Long excludeId) {
    final HashMap<String, Object> condition = new HashMap<>(5);
    condition.put("clientType", clientType);
    condition.put("clientId", clientId);
    condition.put("ownServerId", ownServerId);
    condition.put("excludeId", excludeId);
    return penguinSysClientScopeBusinessMapper.countClientExists(condition) >= 1;
  }


  /**
   * @Description: 保存服务客户端操作
   * @Param: client
   * @return: int
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 下午 4:00
   */
  @Override
  public int savePenguinOauthClient(PenguinOauthClient client) {
    return penguinSysClientScopeBusinessMapper.savePenguinOauthClient(client);
  }

  /**
   * @param id
   * @Description: 获取客户端信息依据id
   * @Param: id
   * @return: com.pkk.cloud.support.oauth2.client.detail.client.entity.PenguinOauthClient
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 下午 4:01
   */
  @Override
  public PenguinOauthClient selectPenguinOauthClientById(Integer id) {
    return penguinSysClientScopeBusinessMapper.selectPenguinOauthClientById(id);
  }

  /**
   * @Description: 更具id更新客户端信息
   * @Param: client
   * @return: int
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 下午 4:02
   */
  @Override
  public int updatePenguinOauthClientById(PenguinOauthClient client) {
    return penguinSysClientScopeBusinessMapper.updatePenguinOauthClientById(client);
  }

  /**
   * @Description: 保存oauth的客户端的信息
   * @Param: penguinOauthClient
   * @return: boolean
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 上午 11:07
   */
  @Override
  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
  public boolean saveOauth2Client(PenguinOauthClient penguinOauthClient) {
    return this.savePenguinOauthClient(penguinOauthClient) == 1;
  }


  /**
   * @Description: 保存客户端授权scope信息
   * @Param: record
   * @return: int
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 下午 4:10
   */
  @Override
  public boolean insertPenguinOauthClientScope(PenguinOauthClientScope record) {
    return penguinSysClientScopeBusinessMapper.insertPenguinOauthClientScope(record) == 1;
  }

  /**
   * @Description: 依据id查询客户端的授权范围的信息
   * @Param: id
   * @return: com.pkk.cloud.support.oauth2.client.detail.client.entity.PenguinOauthClientScope
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 下午 4:10
   */
  @Override
  public PenguinOauthClientScope selectPenguinOauthClientScopeById(Long id) {
    return penguinSysClientScopeBusinessMapper.selectPenguinOauthClientScopeById(id);
  }

  /**
   * @Description: 更新授权范围的信息依据id
   * @Param: record
   * @return: int
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 下午 4:11
   */
  @Override
  public boolean updateByPrimaryKeySelective(PenguinOauthClientScope record) {
    return penguinSysClientScopeBusinessMapper.updatePenguinOauthClientScopeById(record) == 1;
  }

  /**
   * @Description: 获取客户端/客户访问端详情分页查询
   * @Param: page
   * @Param body
   * @return: com.github.pagehelper.PageInfo<com.pkk.cloud.support.admin.dto.resp.client.OauthClientPageRespDto>
   * @Author: peikunkun
   * @Date: 2020/3/30 0030 下午 4:15
   */
  @Override
  public PageInfo<OauthClientDetailRespDto> findOauthClientPage(Page page, OauthClientPageReqDto body) {
    //分页查询
    PageHelper.startPage(page.getPageIndex(), page.getPageSize());
    return new PageInfo<OauthClientDetailRespDto>(penguinSysClientScopeBusinessMapper.findOauthClientPage(body));
  }

  /**
   * @Description: 删除客户端依据id
   * @Param: body
   * @return: boolean
   * @Author: peikunkun
   * @Date: 2020/4/1 0001 下午 4:06
   */
  @Override
  public boolean updateOauthClientCloseById(OauthClientDelReqDto body, String userId) {
    return penguinSysClientScopeBusinessMapper.updateOauthClientCloseById(body.getId(), userId, new Date()) == 1;
  }


  /**
   * @Description: 更新客户端信息依据id
   * @Param: body
   * @return: boolean
   * @Author: peikunkun
   * @Date: 2020/4/1 0001 下午 6:34
   */
  @Override
  public boolean updateOauthClientById(PenguinOauthClient client) {
    return this.updatePenguinOauthClientById(client) == 1;
  }

  /**
   * @Description: 获取客户端信息依据id
   * @Param: id
   * @return: com.pkk.cloud.support.oauth2.client.detail.client.entity.PenguinOauthClient
   * @Author: peikunkun
   * @Date: 2020/4/2 0002 下午 1:49
   */
  @Override
  public PenguinOauthClient getOauthClientById(Long id) {
    return penguinSysClientScopeBusinessMapper.getOauthClientById(id);
  }

  /**
   * @param body
   * @Description: 依据id查询客户端详细信息
   * @Param: body
   * @Author: peikunkun
   * @Date: 2020/4/5 0005 下午 3:12
   */
  @Override
  public OauthClientDetailRespDto findClientById(OauthClientIdReqDto body) {
    final PenguinOauthClient oauthClient = this.getOauthClientById(body.getId());
    final OauthClientDetailRespDto oauthClientDetailRespDto = new OauthClientDetailRespDto();
    BeanUtils.copyProperties(oauthClient, oauthClientDetailRespDto);
    return oauthClientDetailRespDto;
  }

  /**
   * @Description: 获取所有的客户端
   * @Param:
   * @return: java.util.List<com.pkk.cloud.support.oauth2.client.detail.client.entity.PenguinOauthClient>
   * @Author: peikunkun
   * @Date: 2020/4/8 下午9:47
   */
  @Override
  public List<PenguinOauthClient> findAllClientView() {
    return penguinSysClientScopeBusinessMapper.findAllClientView();
  }


  /**
   * @Description: 依据用户id获取用户客户端详情
   * @Param: userId
   * @return: java.util.List<com.pkk.cloud.support.oauth2.client.detail.client.entity.PenguinOauthClient>
   * @Author: peikunkun
   * @Date: 2020/4/8 下午9:57
   */
  @Override
  public List<PenguinOauthClient> findUserClientView(Long userId) {
    return penguinSysClientScopeBusinessMapper.findUserClientView(userId);
  }

  /**
   * @Description: 获取访问客户端的服务组以及服务组下面的客户端信息【服务端->客户端】
   * @Author: peikunkun
   * @Date: 2020/4/22 下午4:21
   */
  @Override
  public List<OauthServerClientScopeByClientRespDto> getBindServerClientByClientId(String clientId) {
    List<OauthServerClientScopeByClientRespDto> finalResult = new ArrayList<>();

    //获取服务端的信息
    List<OauthServerClientBo> server = penguinSysServerService.findSysServerClientConvert();
    if (null == server || server.size() <= 0) {
      return finalResult;
    }

    //获取当前客户端的授权的scope
    Set<String> clientScope = this.findClientScopeByClientId(clientId);

    //获取服务组端下面的所有客户端
    server.stream()
        .collect(Collectors.groupingBy(OauthServerClientBo::getServerCode, LinkedHashMap::new, Collectors.toList()))
        .forEach((serverCodeItem, serverClientList) -> {
          //父级是否选中
          final boolean[] isChecked = {true};

          final String serverName = serverClientList.get(0).getServerName();
          final Long serverId = serverClientList.get(0).getServerId();
          List<OauthServerClientScopeByClientRespDto> childResult = new ArrayList<>();

          //服务端信息
          serverClientList.stream().forEach(childClient -> {
            final boolean contains = clientScope.contains(childClient.getClientId());
            //控制父级
            if (isChecked[0] && !contains) {
              isChecked[0] = false;
            }
            childResult.add(OauthServerClientScopeByClientRespDto.builder().key(childClient.getClientId())
                .title(childClient.getClientName()).type(DEFAULT_RESOURCE_TYPE_CLIENT).primaryId(childClient.getId())
                .checked(contains).build());
          });
          finalResult.add(OauthServerClientScopeByClientRespDto.builder().key(serverCodeItem).title(serverName)
              .children(childResult).type(DEFAULT_RESOURCE_TYPE_SERVER).checked(isChecked[0]).primaryId(serverId)
              .build());
        });
    return finalResult;
  }

  /**
   * @Description: 获取客户端的授权对象
   * @Param: clientId
   * @return: java.util.Set<java.lang.String>
   * @Author: peikunkun
   * @Date: 2020/4/22 0022 下午 4:42
   */
  @Override
  public Set<String> findClientScopeByClientId(String clientId) {
    return penguinSysClientScopeBusinessMapper.findClientScopeByClientId(clientId);
  }

  /**
   * @Description: 绑定客户端的授权服务
   * @Param: clientId
   * @Param scope
   * @return: boolean
   * @Author: peikunkun
   * @Date: 2020/4/22 0022 下午 5:25
   */
  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean bindClientScope(String clientId, Set<String> scopes) {
    //删除原本的绑定
    penguinSysClientScopeBusinessMapper.deleteClientScopeByClientId(clientId);
    if (scopes.size() > 0) {
      penguinSysClientScopeBusinessMapper.batchSaveClientScope(clientId, scopes);
    }
    return true;
  }

  /**
   * @Description: 获取访问客户端的客户端绑定信息
   * @Param: request
   * @return: com.pkk.components.rpc.response.CommonResponse
   * @Author: peikunkun
   * @Date: 2020/4/24 0024 上午 10:07
   */
  @Override
  public List<OauthServerClientByClientVistiRespDto> findVisitClientBindInfo(String visitClientId) {
    List<OauthServerClientByClientVistiRespDto> finalResult = new ArrayList<>();

    //获取服务端的信息
    List<OauthServerClientBo> server = penguinSysServerService.findSysServerClientConvert();
    if (null == server || server.size() <= 0) {
      return finalResult;
    }

    //获取当前客户端的授权的scope
    Set<String> clientScope = this.findClientScopeByClientId(visitClientId);

    //获取服务组端下面的所有客户端
    server.stream()
        .collect(Collectors.groupingBy(OauthServerClientBo::getServerCode, LinkedHashMap::new, Collectors.toList()))
        .forEach((serverCodeItem, serverClientList) -> {
          //父级是否选中
          final boolean[] isChecked = {true};

          final String serverName = serverClientList.get(0).getServerName();
          final Long serverId = serverClientList.get(0).getServerId();
          List<OauthServerClientByClientVistiRespDto> childResult = new ArrayList<>();

          //服务端信息
          serverClientList.stream().forEach(childClient -> {
            final boolean contains = clientScope.contains(childClient.getClientId());
            //控制父级
            if (isChecked[0] && !contains) {
              isChecked[0] = false;
            }
            childResult.add(OauthServerClientByClientVistiRespDto.builder().key(childClient.getClientId())
                .title(childClient.getClientName()).type(DEFAULT_RESOURCE_TYPE_CLIENT).primaryId(childClient.getId())
                .checked(contains).build());
          });
          finalResult.add(OauthServerClientByClientVistiRespDto.builder().key(serverCodeItem).title(serverName)
              .children(childResult).type(DEFAULT_RESOURCE_TYPE_SERVER).checked(isChecked[0]).primaryId(serverId)
              .build());
        });
    return finalResult;
  }


  /**
   * @Description: 访问客户端授权客户端操作
   * @Param: body
   * @return: java.lang.Boolean
   * @Author: peikunkun
   * @Date: 2020/4/24 0024 上午 10:40
   */
  @Override
  public Boolean visitClientBindClientScope(OauthVisitClientBindClientScopeReqDto body) {
    return null;
  }
}
